package com.zxhysy.log.annotation.config;

import com.zxhysy.log.annotation.EnableLog;
import com.zxhysy.log.annotation.advisor.*;
import com.zxhysy.log.annotation.service.*;
import com.zxhysy.log.annotation.advisor.LogSource;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportAware;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;

/**
 * 日志自动配置
 * @author zhangxinhong
 * @since 2021/9/23 14:53
 */
@Configuration(proxyBeanMethods = false)
public class LogAutoConfiguration implements ImportAware {

    /**
     * enableLog 注解
     */
    private AnnotationAttributes enableLog;

    /**
     * 配置默认操作人服务
     * @return 操作人服务
     */
    @Bean
    @ConditionalOnMissingBean(IOperatorGetService.class)
    public IOperatorGetService operatorGetService() {
        return new DefaultOperatorGetServiceImpl();
    }

    /**
     * 默认日志服务，保存需要重写该服务
     * @return 默认日志服务
     */
    @Bean
    @ConditionalOnMissingBean(ILogService.class)
    public ILogService logService() {
        return new DefaultLogServiceImpl();
    }

    /**
     * 数据源
     * @return 数据源
     */
    @Bean
    public LogSource logRecordSource() {
        return new LogSource(enableLog.getBoolean("publicMethodsOnly"), enableLog.getStringArray("tenant"));
    }

    /**
     * 日志函数注册器
     * @return 函数注册器
     */
    @Bean
    public LogFuncRegister logFuncRegister() {
        return new LogFuncRegister();
    }

    /**
     * 拦截方法
     * @param logSource 数据源
     * @return 拦截方法
     */
    @Bean
    public LogInterceptor logInterceptor(LogSource logSource, ILogService logService,
                                         IOperatorGetService iOperatorGetService, LogFuncRegister logFuncRegister) {
        return new LogInterceptor(logSource, logService, iOperatorGetService, logFuncRegister);
    }

    /**
     * 配置处理器
     * @param logSource      数据源
     * @param logInterceptor 拦截方法
     * @return 顾问
     */
    @Bean
    public BeanFactoryLogSourceAdvisor beanFactoryLogOperationSourceAdvisor(LogSource logSource, LogInterceptor logInterceptor) {
        BeanFactoryLogSourceAdvisor advisor = new BeanFactoryLogSourceAdvisor();
        advisor.setPointcut(new LogSourcePointcut(logSource));
        advisor.setAdvice(logInterceptor);
        return advisor;
    }

    @Override
    public void setImportMetadata(AnnotationMetadata importMetadata) {
        // AnnotationMetadata 类上标注的所有注解的封装
        // 使用 @Import 和 importAware 配合使用，可以获取到开启 @EnableLog 所在类的所有注解的封装（元数据 metaData）
        // 参考 AbstractCachingConfiguration
        this.enableLog = AnnotationAttributes.fromMap(
                importMetadata.getAnnotationAttributes(EnableLog.class.
                        getName(), false));
    }
}
